/*
 *  SnackMidi.h
 *  snackbreak
 *
 *  Created by Rua Haszard Morris on 11/21/07.
 *  Copyright 2007 __MyCompanyName__. All rights reserved.

	MIDI support code, i.e. all the code that interacts with portmidi.

 */

#include "portmidi.h"
#include <iostream>

// rua's really dumb midi event - can be a note or a controller and abstracts away the differences between
class MidiEvent
{
public:
	enum Type
	{
		NoEvent = 0,
		Note,
		Pitch
	};
	Type thing;
	int data1;
	int data2;

	static bool MakeMidiEvent(int stat, int d1, int d2, MidiEvent& ev)
	{
		ev.thing = NoEvent;
			ev.data1 = d1;
			ev.data2 = d2;

		if ((stat & 0xF0) == 0x90)
			ev.thing = Note;
		else if ((stat & 0xF0) == 0xe0)
			ev.thing = Pitch;

		return (ev.thing != NoEvent); 
	}

	int getNoteNumber()
	{
		if (thing == Note)
			return data1;
		else
			return -1;
	}
	int getVelocity()
	{
		if (thing == Note)
			return data2;
		else
			return -1;
	}
	double getPitchBend()
	{
		if (thing == Pitch)
			return (data2 - 63) / 127.0;
		else
			return 0.0;
	}
	bool isNoteOn()
	{
		return (getVelocity() > 0);
	}
	bool isNote()
	{
		return (thing == Note);
	}
};

class SnackMidi
{
public:
	static void EnumerateMidiInDevices(std::ostream& strout = std::cout);

public:
	SnackMidi();
	~SnackMidi();
	
	bool OpenInput();
	bool OpenInput(PmDeviceID midiDev);
	void CloseInput();

	bool CheckForEvent(MidiEvent& eventInfo);

private:
	static int IsNoteOn(PmMessage msg);

private:
   PmStream * midi;
};